#include "head.h"

int main(int argc, char const *argv[])
{
    system("clear");
    if (initDatabase("abc") == -1)
    {
        return 0;
    }

    struct sockaddr_in sin;
    sin.sin_family = AF_INET;   // IPV4的网络地址版本
    sin.sin_port = htons(9001); // 把9000号端口转为网络字节序并赋值给端口参数

    u_int32_t ip = 0;
    // 把字符串ip地址转为网络字节序ip
    inet_pton(AF_INET, "192.168.91.120", &ip);
    sin.sin_addr.s_addr = ip;

    // 创建一个tcp套接字，参数1指定地址族，参数2指定协议，SOCK_STREAM代表是TCP，SOCK_DGRAM代表UDP
    int sID = socket(AF_INET, SOCK_STREAM, 0);

    // 把套接字和地址绑定（手机+手机号）
    if (-1 == bind(sID, (struct sockaddr *)&sin, sizeof(sin)))
    {
        perror("绑定地址失败，请等待30秒或者换一个端口试试");
        return 0;
    }

    // 打开监听功能，监听绑定地址上的来访请求，5代表同时允许5个客户端排队连接
    listen(sID, 5);

    printf("\t  \033[41m\033[37m云领仓储系统\033[0m\n");

    // 定义一个MAX_EVENT个事件结构体，每个结构体中都有感兴趣的事件和套接字
    struct epoll_event ev, events[MAX_EVENT];

    // 创建一个epoll对象
    int epoll_id = epoll_create(MAX_EVENT);

    ev.events = EPOLLIN; // 感兴趣的事件 为 有数据可读
    ev.data.fd = sID;    // 感兴趣的套接字

    epoll_ctl(epoll_id, EPOLL_CTL_ADD, sID, &ev);

    while (1)
    {
        int count = epoll_wait(epoll_id, events, MAX_EVENT, -1);
        if (count == -1)
        {
            perror("epoll_wait");
            return 0;
        }
        for (size_t i = 0; i < count; i++)
        {
            int fd = events[i].data.fd;
            struct sockaddr_in clientAddr;
            socklen_t len = sizeof(clientAddr);
            if (fd == sID)
            {
                int new_fd = accept(fd, (struct sockaddr *)&clientAddr, &len);
                // 产生一个新的套接字，需要给他一个结构，并写入epoll中管理
                ev.data.fd = new_fd; // 把新的套接字赋值给结构体
                if (0 == (epoll_ctl(epoll_id, EPOLL_CTL_ADD, new_fd, &ev)))
                {
                    printf("套接字加入epoll成功\n");
                }
            }
            else
            {
                MSG msg;
                int ret = recv(fd, &msg, sizeof(MSG), 0);
                if (ret <= 0) // 表示有客户端推出，则要移除套接字
                {
                    ev.data.fd = fd;
                    if (0 == epoll_ctl(epoll_id, EPOLL_CTL_DEL, fd, &ev))
                    {
                        printf("从epoll中移除套接字结构体成功\n");
                    }
                    else
                    {
                        printf("从epoll中移除套接字结构体失败\n");
                    }
                    close(fd);
                    continue;
                }
                warehouse(fd, msg, clientAddr);
            }
        }
    }
    close(sID);

    return 0;
}
